import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Random;
import java.util.StringTokenizer;


public class AlienShip extends ShipObject
{
	private final static int SIZE = 15; // radius of the ship
	private double speedFactorMin = 0.5; // above this speed, accelerate
	private double speedFactorMax = 0.6; // above this speed, brake
	
    protected int hitCount;
	
	private final static int SHOOT_DELAY = 6; // time factor multiplied into shooting times
	private final static int MAX_HITS = 3;
	
	public final static int POINTS = 100;
	
	private BufferedImage image;
	
	public AlienShip(int x, int y, int level)
	{
		super(x,y);
		speedFactorMin = 0.5 + level/5.0; // get faster as level increases
		speedFactorMax = 0.6 + level/4.0;
		
		hitCount = MAX_HITS;
		
		drawImage();
	}
	
	public AlienShip(StringTokenizer strtok, int level)
	{
		super();
		loadState(strtok);
		
		speedFactorMin = 0.5 + level/5.0; // get faster as level increases
		speedFactorMax = 0.6 + level/4.0;
		drawImage();
	}
	
	private void drawImage()
	{
		final int[] xvals_alien = {-SIZE/2, -SIZE, -SIZE/2, SIZE/2, SIZE, SIZE/2, 
				-SIZE/2, SIZE/2, SIZE/3, SIZE/5, -SIZE/5, -SIZE/3};
		final int[] yvals_alien = {-SIZE/2, 0,     SIZE/2,  SIZE/2, 0,   -SIZE/2, 
				-SIZE/2, -SIZE/2, -SIZE/2, -SIZE*4/5, -SIZE*4/5, -SIZE/2};
		// since the image would go all the way to the edge, add a little buffer
		// so that the outside pixels don't get cut off
		image = new BufferedImage(2*SIZE+2, 2*SIZE+2, BufferedImage.TYPE_INT_ARGB);
		
		Graphics2D g = image.createGraphics();
		g.setColor(Color.WHITE);
		g.translate(image.getWidth()/2, image.getHeight()/2); // center of image
		g.rotate(direction);
		g.drawPolygon(xvals_alien, yvals_alien, xvals_alien.length);
		g.dispose();
	}
	
	// implement methods from SpaceObject and MovingObject
	public BufferedImage getImage() { return image; }
	public int getWrapWidth() { return SIZE*2; } // alien ships will never be rotated, so the entire image is used
	public int getWrapHeight() { return SIZE*2; }
	
	// Implement collision functions
	public CollisionType collisionType() { return CollisionType.CIRCLE; }
	public double[] collisionData()
	{
		// center + radius
		double[] circle = {x, y, SIZE};
		return circle;
	}
	
	protected void loadState(StringTokenizer strtok) throws NumberFormatException
	{
		super.loadState(strtok);
		hitCount = Integer.parseInt(strtok.nextToken());
	}
	protected String saveState()
	{
		return "AlienShip " + super.saveState() + String.format("%d\n", hitCount);
	}
	
	// Implements hit() from SpaceObject
	// an AlienShip can be hit by a Bullet or Spaceship or GravitationalObject
	public boolean hit(SpaceObject by)
	{
		if(by instanceof Bullet)
		{
			// note that other alien or rogue spaceships can shoot alien ships
			if(((Bullet)by).isShooter(this))
				return false; // can't shoot myself
			
			// play hit sound
			AsteroidsGame.soundManager.play(AsteroidsGame.alien_hit);
			hitCount--;
			if(hitCount > 0)
				return false;
			
			// play kill sound
			AsteroidsGame.soundManager.play(AsteroidsGame.alien_explosion);
			if(((Bullet)by).isShooter(AsteroidsGame.game.player1))
				AsteroidsGame.game.score(1, POINTS);
			if(((Bullet)by).isShooter(AsteroidsGame.game.player2))
				AsteroidsGame.game.score(2, POINTS);
		}
		else if(by instanceof Spaceship) // hitting a spaceship instantly destroys an alien
		{
			if(((Spaceship)by).isRogue()) // rogue spaceships have no effect on alien ships
				return false;
			// no points for destroying an alien with your face
		}
		// else if hit by the planet, just destroyed with no further effects
		
		delete();
		return true;
	}
	
	// Overrides move() from ShipObject
	public void move()
	{
		alienAI();
		super.move();
		
		Random rng = AsteroidsGame.rng;
		
		// alien ships need to shoot randomly, not in their direction
		// so instead of using the shooting flag, we make bullets ourselves, here
		if(shotCooldown <= 0 && burstCount > 0)
    	{
			// store the old direction, so we shoot randomly without changing movement
			double moveDirection = direction; 
			direction = rng.nextDouble() * 2*Math.PI;
			AsteroidsGame.game.addObject(new Bullet((int)x, (int)y, this));
			AsteroidsGame.soundManager.play(AsteroidsGame.laser);
			direction = moveDirection;
			
			burstCount--;
			shotCooldown = SHOT_TIME*SHOOT_DELAY; // time between shots
			burstCooldown = BURST_TIME*SHOOT_DELAY; // start timer for next burst
    	}
    	// if burst timer has expired, reset shot count once
    	if(burstCount < BURST_SHOTS && burstCooldown <= 0)
    	{
    		burstCount = BURST_SHOTS;
    	}
	}
	
	// Alien ships shoot randomly, but shoot more often than rogue spaceships
	// They will try to maintain a speed of less than the normal maximum speed,
	// and never change directions on their own
	private void alienAI()
	{
		
		if(getSpeed() < MAX_SPEED*speedFactorMin)
			accelerating = 1;
		else if(getSpeed() > MAX_SPEED*speedFactorMax)
			accelerating = -1;
		else
			accelerating = 0;
	}
}
